﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web;
using ABC.Core.Configuration;
using ABC.Core.Providers;

namespace ABC.Business.Models
{

    public class YandexDiskModel
    {
        private static readonly IApplicationSettingsProvider ApplicationSettingsProvider = IoC.Resolve<IApplicationSettingsProvider>();
        private string token = ApplicationSettingsProvider.YandexDiskToken;  // доступ к аккаунту логин azbuka244, пароль azbuka24
        public string Error { get; set; }

        private void Init(string error)
        {
            Error = error;
        }

        public YandexDiskModel()
        {
            Init("no errors");
        }

        /// <summary>
        /// Запрос возвращает информацию о папке dir и всех папках и файлах в нем
        /// </summary>
        /// <param name="dir">Папка</param>
        /// <returns>Список файлов и папок в папке dir или null если произошла ошибка</returns>
        public List<DirInfo> GetDirectoriesInfo(string dir)
        {
            var myweb = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + dir);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Method = "PROPFIND";

            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
                var sr = new StreamReader(resp.GetResponseStream());
                string cont = sr.ReadToEnd();
                var dinfo = new List<DirInfo>();
                int posBeg, posEnd;
                while (true)
                {
                    posBeg = cont.IndexOf("<d:response>");
                    posEnd = cont.IndexOf("</d:response>");
                    if (posBeg < 0) break;
                    dinfo.Add(ParseDirInfo(cont.Substring(posBeg, posEnd - posBeg)));
                    cont = cont.Substring(posEnd + 1);
                }

                return dinfo;
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return null;
            }
        }

        /// <summary>
        /// Запрос удаляет папку (или файл) dir
        /// </summary>
        /// <param name="dir">Папка (или файл) которую надо удалить</param>
        /// <returns>true если запрос выполнен успешно</returns>
        public bool DeleteDirectoryOrFile(string dir)
        {
            var myweb = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + dir);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Method = "DELETE";

            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return false;
            }
            return true;
        }

        public bool MoveFile(string dirWith, string dirTo, string dirInTo, string fileName)
        {
            const string url = "https://webdav.yandex.ru/";
            var strSourceUri = url + dirWith + "/" + fileName;
            var strDestUri = url + dirTo + "/" + dirInTo + "/" + fileName;

            var myweb = (HttpWebRequest)WebRequest.Create(strSourceUri);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Headers.Add("Depth: 1");
            myweb.Method = "MOVE";
            myweb.Headers.Add("Destination", strDestUri);
            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return false;
            }
            return true;
        }

        /// <summary>
        /// Запрос создает папку dir на сервере
        /// </summary>
        /// <param name="dir">Название папки</param>
        /// <returns>true если запрос выполнен успешно</returns>
        public bool CreateDirectory(string dir)
        {
            var myweb = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + dir);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Method = "MKCOL";

            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return false;
            }
            return true;
        }

        /// <summary>
        /// Запрос отправляет файл на сервер
        /// </summary>
        /// <param name="dir">Название файла на сервере (путь к файлу)</param>
        /// <param name="file">Загружаемый файл</param>
        /// <param name="fileName">Имя файла на сервере</param>
        /// <param name="mimeType">MIME-тип файла</param>
        /// <returns>true если запрос выполнен успешно</returns>
        public bool UploadFile(string dir, HttpPostedFileBase file, string fileName, string mimeType)
        {
            var myweb = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + dir + "/" + fileName);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Method = "PUT";
            myweb.ContentType = mimeType;
            try
            {
                using (Stream myReqStream = myweb.GetRequestStream())
                {
                    file.InputStream.CopyTo(myReqStream);
                }
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return false;
            }

            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return false;
            }

            return true;
        }

        /// <summary>
        /// Запрос скачивает файл с сервера
        /// </summary>
        /// <param name="dir">Путь к файлу на сервере</param>
        /// <param name="myfile">Название файла</param>
        /// <returns>true если запрос выполнен успешно</returns>
        public Stream DownloadFile(string dir)
        {
            var myweb = (HttpWebRequest)WebRequest.Create("https://webdav.yandex.ru/" + dir);
            myweb.Accept = "*/*";
            myweb.Headers.Add("Depth: 1");
            myweb.Headers.Add("Authorization: OAuth " + token);
            myweb.Method = "GET";

            try
            {
                var resp = (HttpWebResponse)myweb.GetResponse();
                return resp.GetResponseStream();
            }
            catch (Exception ex)
            {
                Error = ex.Message;
                return null;
            }
        }

        private DirInfo ParseDirInfo(string xml)
        {
            var rez = new DirInfo();
            rez.CreationDate = DirInfo.GetData(xml, "creationdate");
            rez.DisplayName = DirInfo.GetData(xml, "displayname");
            rez.ContentLenght = Convert.ToInt32(DirInfo.GetData(xml, "getcontentlength"));
            rez.LastModified = DirInfo.GetData(xml, "getlastmodified");
            rez.ContentType = rez.ContentLenght != 0 ? DirInfo.GetData(xml, "getcontenttype") : "";
            return rez;
        }
    }

    public class DirInfo
    {
        public DirInfo() { }

        public string DisplayName { get; set; }

        public int ContentLenght { get; set; }

        public string CreationDate { get; set; }

        public string LastModified { get; set; }

        public string ContentType { get; set; }


        public static string GetData(string xml, string tag)
        {
            int p1, p2;
            p1 = xml.IndexOf("<d:" + tag + ">");
            p2 = xml.IndexOf("</d:" + tag + ">");
            return xml.Substring(p1 + tag.Length + 4, p2 - 4 - (p1 + tag.Length));
        }
    }
}
